﻿#ifndef TRUEROUNDNESS_H
#define TRUEROUNDNESS_H

#include <opencv2/opencv.hpp>

/**
 * @brief The TrueRoundness class 真圆度计算。只实现了一种最基本的算法。
 */
class TrueRoundness
{
public:
    /**
     * @brief TrueRoundness 真圆度计算的类的构造函数。考虑到除去噪声影响，可以排除部分数据点。
     * @param top 计算真圆度时，最大直径排除前 top 个点。
     * @param bottom 计算真圆度时，最小直径排除最后 bottom 个点。
     */
    TrueRoundness(unsigned int top = 0, unsigned int bottom = 0);//可以去除两头的一部分数据
    /**
     * @brief TrueRoundness 真圆度计算的类的构造函数。考虑到除去噪声影响，可以排除部分数据点。
     * @param top_percent 计算真圆度时，最大直径排除前 top_percent % 的点。
     * @param bottom_percent 计算真圆度时，最小直径排除最后 bottom_percent % 的点。
     */
    TrueRoundness(double top_percent, double bottom_percent); //去除两头一定比例的数据

    /**
     * @brief operator ()计算真圆度。首先计算出拟合圆，然后计算轮廓上到点到圆心的最远距离和最近距离。之差就是真圆度。
     * @param [in] contour 轮廓上的点。
     * @param [out] r_min
     * @param [out] r_max
     * @return  返回真圆度。如果结果小于 0 ，则表示计算失败。通常是拟合圆失败。
     */
    double operator() (const std::vector<cv::Point2i> &contour, double &r_min, double &r_max);
    double operator() (const std::vector<cv::Point2f> &contour, double &r_min, double &r_max);
    /**
     * @brief circleLeastFit 最小二乘法拟合圆。这个函数是辅助函数，通常不需要使用。
     * @param points 圆的轮廓上的点
     * @param center_x 计算出的圆心坐标 x
     * @param center_y 计算出的圆心坐标 y
     * @param radius 计算出的半径值
     * @return true 表示拟合成功。false 表示失败。
     */
    bool circleLeastFit(const std::vector<cv::Point2i> &points, double &center_x, double &center_y, double &radius);
    bool circleLeastFit(const std::vector<cv::Point2f> &points, double &center_x, double &center_y, double &radius);

    /**
     * @brief sort 辅助函数，对边缘数据进行排序，离圆心远的数据排在前面。
     * @param contour 轮廓上的点
     * @param center_x 圆心坐标 x
     * @param center_y 圆心坐标 y
     */
    void sort( std::vector<cv::Point2i> &contour, double center_x, double center_y );
    void sort( std::vector<cv::Point2f> &contour, double center_x, double center_y );

    /**
     * @brief distance 辅助函数，计算一个点到圆心的距离
     * @param p
     * @param center_x
     * @param center_y
     * @return
     */
    double distance(cv::Point2i p, double center_x, double center_y);
    double distance(cv::Point2f p, double center_x, double center_y);
private:
    int m_type = 0;
    int m_top = 0;
    int m_bottom = 0;
    double m_top_percent = 0;
    double m_bottom_percent = 0;
};

#endif // TRUEROUNDNESS_H
